@file:OptIn(
    ExperimentalFoundationApi::class, ExperimentalFoundationApi::class,
    ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class,
    ExperimentalFoundationApi::class
)

package com.example.result.books

import android.Manifest
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Environment
import android.provider.Settings
import android.util.Log
import androidx.activity.compose.BackHandler
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Sort
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.Create
import androidx.compose.material.icons.filled.FileUpload
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.MoveUp
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Share
import androidx.compose.material.icons.filled.TypeSpecimen
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.DrawerState
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilledIconToggleButton
import androidx.compose.material3.FilterChip
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Label
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SuggestionChip
import androidx.compose.material3.SuggestionChipDefaults
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.rememberDrawerState
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.core.content.ContextCompat
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.example.result.R
import com.example.result.ui.theme.LocalMessage
import com.example.result.ui.theme.ShouldShowRationalPermissionLocal
import com.lly.tboc.zhouyi.Screen
import com.lly.tboc.zhouyi.Screen.Dao.startElli
import com.lly.tboc.zhouyi.Screen.Dao.suffix
import com.lly.tboc.zhouyi.Screen.Yao.isAssets
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale


@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FileFinder() {
    val booksViewModel = hiltViewModel<BooksViewModel>()
    val drawerState = rememberDrawerState(initialValue = DrawerValue.Open)
    var path: Screen.WebView.FileAddress? by rememberSaveable {
        mutableStateOf(null)
    }
    val scope = rememberCoroutineScope()
    val scrollBehavior =
        TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState())
    val snackBarHostState = remember {
        SnackbarHostState()
    }
    if (drawerState.isClosed) {
        BackHandler {
            scope.launch {
                drawerState.open()
            }
        }
    }
    Box {
        ModalNavigationDrawer(
            drawerState = drawerState,
            gesturesEnabled = drawerState.isOpen,
            drawerContent = {
                val bookMarks by booksViewModel.bookMarks.collectAsState(initial = BookMarks())
                val defaultBookMarks = booksViewModel.defaultBookMarks
                val books = booksViewModel.books
                BookDrawerContent(
                    defaultBookMarks, bookMarks, books, booksViewModel,
                    { path = Screen.WebView.FileAddress.Path(it) },
                    drawerState
                )
            }) {
            Scaffold(
                modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
                topBar = {
                    BookTopBar(path, scope, drawerState, scrollBehavior, booksViewModel)
                },
                snackbarHost = {
                    if (drawerState.isClosed) {
                        SnackbarHost(hostState = snackBarHostState)
                    }
                },
                bottomBar = {
                },
                containerColor = Color.Transparent,
            ) { paddingValues ->
                val modifier = Modifier.padding(paddingValues)
                Column {
                    path?.let {
                        WebViewScreen(modifier, fileAddress = it, booksViewModel)
                    } ?: Surface(modifier) {

                    }
                }
            }
            if (drawerState.isClosed) {
                handleMessage(booksViewModel, scope, snackBarHostState)
            }
        }
        if (drawerState.isOpen) {
            SnackbarHost(
                hostState = snackBarHostState, modifier = Modifier
                    .padding(bottom = 24.dp)
                    .align(
                        Alignment.BottomCenter
                    )
            )
            handleMessage(booksViewModel, scope, snackBarHostState)
        }
    }
}

@Composable
fun RenameDialog(
    showState: MutableState<Boolean>,
    defaultName: String,
    execAction: (String) -> Unit
) {
    if (showState.value) {
        val filename = mutableStateOf(defaultName)
        val onDismissRequest = { showState.value = false }
        Dialog(onDismissRequest = { onDismissRequest() }) {
            Card(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp),
                shape = RoundedCornerShape(16.dp),
            ) {
                TextField(
                    value = filename.value,
                    isError = filename.value.isBlank(),
                    onValueChange = {
                        filename.value = it
                    },
                    label = { Text(text = "文件名") },
                    modifier = Modifier
                        .wrapContentSize(Alignment.Center),
                )
                val modifier = Modifier
                    .padding(8.dp)
                    .align(Alignment.CenterHorizontally)
                Button(
                    modifier = modifier,
                    onClick = {
                        if (filename.value.isNotBlank()) {
                            onDismissRequest()
                            execAction(filename.value)
                        }
                    }) {
                    Text(text = "保存")
                }
                Button(modifier = modifier, onClick = {
                    filename.value = ""
                    onDismissRequest()
                }) {
                    Text(text = "取消")
                }
                Button(modifier = modifier, onClick = {
                    filename.value = defaultName
                }) {
                    Text(text = "恢复默认")
                }
            }
        }

    }
}

@Composable
fun handleMessage(
    booksViewModel: BooksViewModel,
    scope: CoroutineScope,
    snackBarHostState: SnackbarHostState
) {
    val message by booksViewModel.message.collectAsState()
    if (message.isNotEmpty()) {
        Log.e("handleMessage", message)
        scope.launch {
            snackBarHostState.showSnackbar(
                message,
                withDismissAction = true,
                duration = SnackbarDuration.Short
            )
        }
        booksViewModel.afterMessageShow()
    }
    val message2 by LocalMessage.current.msg.collectAsState()
    if (message2.isNotEmpty()) {
        Log.e("handleMessage", message2)
        scope.launch {
            snackBarHostState.showSnackbar(
                message2,
                withDismissAction = true,
                duration = SnackbarDuration.Short
            )
        }
        LocalMessage.current.msg.value = ""
    }
}

@Composable
private fun BookDrawerContent(
    defaultBookMarks: Array<String>,
    bookMarks: BookMarks,
    books: Flow<List<Book>>,
    directoryManager: DirectoryManager,
    showFileContent: (String) -> Unit,
    drawerState: DrawerState
) {
    ModalDrawerSheet {
        var showBookMarks by rememberSaveable {
            mutableStateOf(true)
        }
        val path by directoryManager.currentDir.map { it?.path() ?: "" }.collectAsState("")
        val recentExplorer by directoryManager.recentExplorer.collectAsState(initial = emptyList())

        if (showBookMarks) {
            Button(modifier = Modifier.padding(8.dp), onClick = { showBookMarks = false }) {
                Text(text = "返回文件列表")
            }
            LazyColumn(modifier = Modifier.padding(8.dp)) {
                stickyHeader { Text(text = "默认书签") }
                items(defaultBookMarks, key = { it }) {
                    BookMarkItem({
                        directoryManager.switchTo(it)
                        showBookMarks = false
                    }, directoryManager::removeBookMark, it, path)
                }
                stickyHeader {
                    Label(label = { Text(text = "ads") }) {
                        Text(text = "其他书签")
                    }
                }
                items(bookMarks.bookMarks, key = { "bookMarks$it" }) {
                    BookMarkItem({
                        directoryManager.switchTo(it)
                        showBookMarks = false
                    }, directoryManager::removeBookMark, it, path)
                }
                if (recentExplorer.isNotEmpty()) {
                    stickyHeader {
                        Label(label = { Text(text = "ads") }) {
                            Text(text = "最近浏览")
                        }
                    }
                    items(recentExplorer, key = { "recentExplorer$it" }) {
                        BookMarkItem({
                            directoryManager.switchTo(it)
                            showBookMarks = false
                        }, directoryManager::removeBookMark, it, path)
                    }
                }

            }
        } else {
            val scope = rememberCoroutineScope()
            Row(
                modifier = Modifier.padding(8.dp),
                horizontalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                Button(onClick = { showBookMarks = true }) {
                    Text(text = "返回书签\n列表")
                }
                val isBookMark = bookMarks.bookMarks.contains(path)
                Button(onClick = {
                    if (isBookMark) {
                        directoryManager.removeBookMark(path)
                    } else {
                        directoryManager.addBookMark(path)
                    }
                }) {
                    Text(text = if (isBookMark) "取消\n该书签" else "设置该路径\n为书签")
                }
            }

            SuggestionChip(modifier = Modifier.padding(8.dp),
                onClick = { },
                label = { Text(text = "当前路径:\n${path.startElli()}") })

            var showSortUI by remember {
                mutableStateOf(false)
            }
            var filterKeyword by remember {
                mutableStateOf("")
            }
            Row(
                modifier = Modifier.padding(8.dp),
            ) {
                var expandFilterEdit by remember {
                    mutableStateOf(false)
                }
                if (!expandFilterEdit) {
                    if (!path.isAssets()) {
                        val showState = remember {
                            mutableStateOf(false)
                        }
                        RenameDialog(
                            showState = showState,
                            defaultName = SimpleDateFormat(
                                "MM/dd/yyyy",
                                Locale.CHINA
                            ).format(Calendar.getInstance().time) + ".txt",
                            execAction = { directoryManager.createFile(it) })

                        IconButton(onClick = {
                            showState.value = true
                        }) {
                            Icon(Icons.Default.Create, contentDescription = "createFile")
                        }
                    }
                    IconButton(onClick = { directoryManager.moveUp() }) {
                        Icon(Icons.Default.MoveUp, contentDescription = "moveUp")
                    }
                    IconButton(onClick = { directoryManager.refresh() }) {
                        Icon(Icons.Default.Refresh, contentDescription = "refresh")
                    }
                    FilledIconToggleButton(
                        checked = showSortUI,
                        onCheckedChange = { showSortUI = !showSortUI }) {
                        Icon(imageVector = Icons.AutoMirrored.Filled.Sort, "排序")
                    }
                }
                if (expandFilterEdit) {
                    TextField(
                        value = filterKeyword,
                        onValueChange = { filterKeyword = it.lowercase() },
                        leadingIcon = {
                            Icon(
                                Icons.Default.Search,
                                contentDescription = "search",
                                modifier = Modifier.clickable {
                                    expandFilterEdit = false
                                })
                        },
                        trailingIcon = {
                            val keyboardController = LocalSoftwareKeyboardController.current
                            if (filterKeyword.isNotEmpty()) {
                                IconButton(onClick = {
                                    filterKeyword = ""
                                    keyboardController?.hide()
                                }) {
                                    Icon(Icons.Default.Clear, contentDescription = "clear")
                                }
                            }

                        })
                } else {
                    IconButton(onClick = { expandFilterEdit = true }) {
                        Icon(Icons.Default.Search, contentDescription = "search")
                    }
                }
            }
            SortUI(showSortUI, directoryManager)
            FilePermissionView {
                directoryManager.refresh()
            }
            BooksScreen(
                books.map {
                    if (filterKeyword.isNotEmpty()) it.filter {
                        it.name.lowercase().contains(
                            filterKeyword
                        )
                    } else it
                }.collectAsState(emptyList()).value,
                directoryManager
            ) {
                showFileContent(it)
                scope.launch {
                    drawerState.close()
                }
            }


        }
    }
}

@Composable
private fun FilePermissionView(refresh: () -> Unit) {
    val context = LocalContext.current

    FileManagerPermissionSuggestion(context, refresh)

    if (ContextCompat.checkSelfPermission(
            context,
            Manifest.permission.READ_EXTERNAL_STORAGE
        ) == PackageManager.PERMISSION_DENIED
    ) {
        var showSuggest by remember {
            mutableStateOf(true)
        }
        val launcher = rememberLauncherForActivityResult(
            ActivityResultContracts.RequestPermission()
        ) { isGranted ->
            showSuggest = !isGranted
            if (isGranted) {
                refresh()
            }
        }

        if (showSuggest) {
            SuggestionChip(
                colors = SuggestionChipDefaults.suggestionChipColors()
                    .copy(containerColor = MaterialTheme.colorScheme.errorContainer), onClick = {
                    launcher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
                }, label = {
                    Text(text = "外部文件读取权限")
                }
            )
            if (ShouldShowRationalPermissionLocal.current.readStorage.value) {
                Text(text = "获取外部文件必须")
            }
        }

    }
}

@Composable
fun FileManagerPermissionSuggestion(context: Context, refresh: () -> Unit) {
    var externalStorageManager by remember { mutableStateOf(true) }
    val current = LocalLifecycleOwner.current
    LaunchedEffect(true) {
        current.repeatOnLifecycle(Lifecycle.State.RESUMED) {
            val t = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                Environment.isExternalStorageManager()
            } else {
                true
            }
            if (t && externalStorageManager != t) {
                refresh()
            }
            externalStorageManager = t
        }
    }
    if (!externalStorageManager) {
        SuggestionChip(
            colors = SuggestionChipDefaults.suggestionChipColors()
                .copy(containerColor = MaterialTheme.colorScheme.errorContainer), onClick = {
                context.startActivity(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION).apply {
                    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
                })
            }, label = {
                Text(text = "授予管理所有文件的权限")
            }
        )
        if (ShouldShowRationalPermissionLocal.current.fileManager.value) {
            Text(text = "Android 10 以上获取部分外部文件必须")
        }
    }
}

@Composable
private fun SortUI(
    showSortUI: Boolean,
    directoryManager: DirectoryManager
) {
    if (showSortUI) {
        val bookSortTypeState by directoryManager.currentBookSort.collectAsState()
        Row(
            modifier = Modifier.padding(8.dp),
            horizontalArrangement = Arrangement.spacedBy(8.dp),
        ) {
            arrayOf(
                SortCategory.Name,
                SortCategory.TotalSpace,
                SortCategory.ModifierTime
            ).forEach {
                FilterChip(
                    selected = bookSortTypeState.sortCategory == it,
                    onClick = {
                        directoryManager.sort(bookSortTypeState.copy(sortCategory = it))
                    },
                    label = { Text(text = it.displayName) })
            }
        }
        Row(
            modifier = Modifier.padding(8.dp),
            horizontalArrangement = Arrangement.spacedBy(8.dp),
        ) {
            arrayOf(
                SortType.Asc,
                SortType.Desc,
            ).forEach {
                FilterChip(
                    selected = bookSortTypeState.sortType == it,
                    onClick = {
                        directoryManager.sort(bookSortTypeState.copy(sortType = it))
                    },
                    label = { Text(text = it.displayName) })
            }
        }
    }
}

@Composable
private fun BookMarkItem(
    switchTo: (String) -> Unit,
    delete: (String) -> Unit,
    it: String,
    path: String?,
) {
    var canShow by remember {
        mutableStateOf(false)
    }
    if (canShow) {
        AlertDialog(
            onDismissRequest = { canShow = false },
            confirmButton = {
                Button(onClick = {
                    delete(it)
                    canShow = false
                }) {
                    Text(text = stringResource(id = R.string.ok))
                }
            },
            dismissButton = {
                Button(
                    onClick = {
                        canShow = false
                    }) {
                    Text(text = stringResource(id = R.string.cancel))
                }
            }, text = {
                Text(text = "删除书签")
            }
        )
    }
    SuggestionChip(onClick = { }, label = {
        Text(
            modifier = Modifier.combinedClickable(
                onLongClick = {
                    canShow = true
                },
                onLongClickLabel = "删除书签"
            ) { switchTo(it) },
            text = if (it.length > 30) "..." + it.substring(it.length - 30) else it,
            overflow = TextOverflow.Ellipsis,
            maxLines = 1,
            color = if (path == it) MaterialTheme.colorScheme.secondary else MaterialTheme.colorScheme.tertiary
        )
    })
}

fun putTextIntoClip(context: Context, label: String, text: String) {
    val clipboardManager: ClipboardManager =
        context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    //创建ClipData对象
    val clipData = ClipData.newPlainText(label, text)
    //添加ClipData对象到剪切板中
    clipboardManager.setPrimaryClip(clipData)
}

@Composable
@OptIn(ExperimentalMaterial3Api::class)
private fun BookTopBar(
    path: Screen.WebView.FileAddress?,
    scope: CoroutineScope,
    drawerState: DrawerState,
    scrollBehavior: TopAppBarScrollBehavior,
    fileOperation: FileOperation
) {
    val context = LocalContext.current
    val message = LocalMessage.current
    TopAppBar(
        title = {
            Text(text = path?.let {
                it.path.let {
                    it.substring(
                        maxOf(
                            it.indexOfLast { '/' == it },
                            0
                        )
                    )
                }
            } ?: "", modifier = Modifier
                .basicMarquee()
                .combinedClickable {
                    path?.let {
                        putTextIntoClip(context, "filepath", it.path)
                        message.msg.value = "文件路径已拷贝到剪切版"
                    }
                })
        },
        navigationIcon = {
            Icon(
                Icons.Filled.Menu,
                contentDescription = "",
                modifier = Modifier
                    .clickable {
//                                navigateAction()
                        scope.launch { drawerState.open() }
                    }
                    .padding(16.dp)
            )
        },
        actions = {
            path?.let { path ->
                val suffix = path.path.suffix()
                val fileTypeMapDataStore = LocalContext.current.fileTypeMapDataStore
                val needShowSelectDialog = remember {
                    mutableStateOf(false)
                }
                if (needShowSelectDialog.value) {
                    SelectFileTypeDialog(suffix, fileTypeMapDataStore, needShowSelectDialog)
                }
                IconButton(onClick = { needShowSelectDialog.value = true }) {
                    Icon(
                        Icons.Filled.TypeSpecimen,
                        contentDescription = "fileTypeChange",
                    )
                }
                var showMoreDialog by remember {
                    mutableStateOf(false)
                }
                IconButton(onClick = { showMoreDialog = true }) {
                    Icon(Icons.Default.Menu, contentDescription = "menu")
                    DropdownMenu(
                        expanded = showMoreDialog,
                        offset = DpOffset((-8).dp, 0.dp),
                        onDismissRequest = { showMoreDialog = false }) {
                        IconButton(onClick = {
                            fileOperation.shareFile(context, path.path)
                            showMoreDialog = false
                        }) {
                            Icon(Icons.Default.Share, contentDescription = "share")
                        }
                        IconButton(onClick = {
                            fileOperation.uploadFile(path.path)
                            showMoreDialog = false
                        }) {
                            Icon(Icons.Default.FileUpload, contentDescription = "FileUpload")
                        }
                        /*
                                        IconButton(onClick = {
                                            fileOperation.saveToFile(context, path.path)
                                        }) {
                                            Icon(Icons.Default.SaveAs, contentDescription = "SaveAs")
                                        }
                        */
                    }
                }

            }

        },
        scrollBehavior = scrollBehavior,
    )
}